<!DOCTYPE html>
<html lang="zh-CN" data-theme="light">
  <head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width,initial-scale=1" />
    <meta name="generator" content="VuePress 2.0.0-beta.53" />
    <meta name="theme" content="VuePress Theme Hope" />
    <link rel="icon" href="/doc/images/favicon.ico"><title>控制器 | AT 的文档库</title><meta name="description" content="At 的文档库，好记性不如烂笔头！">
    <style>
      :root {
        --bg-color: #fff;
      }

      html[data-theme="dark"] {
        --bg-color: #1d2025;
      }

      html,
      body {
        background: var(--bg-color);
      }
    </style>
    <script>
      const userMode = localStorage.getItem("vuepress-theme-hope-scheme");
      const systemDarkMode =
        window.matchMedia &&
        window.matchMedia("(prefers-color-scheme: dark)").matches;

      if (userMode === "dark" || (userMode !== "light" && systemDarkMode)) {
        document.querySelector("html").setAttribute("data-theme", "dark");
      }
    </script>
    <link rel="preload" href="/doc/assets/style.c3a4c10b.css" as="style" /><link rel="stylesheet" href="/doc/assets/style.c3a4c10b.css" />
    <link rel="modulepreload" href="/doc/assets/app.41440b49.js"><link rel="modulepreload" href="/doc/assets/Controllers.html.029df1e7.js"><link rel="modulepreload" href="/doc/assets/_plugin-vue_export-helper.cdc0426e.js"><link rel="modulepreload" href="/doc/assets/Controllers.html.6b27764c.js"><link rel="prefetch" href="/doc/assets/index.html.0bcc895f.js" as="script" /><link rel="prefetch" href="/doc/assets/index.html.c8df2167.js" as="script" /><link rel="prefetch" href="/doc/assets/Vue2.html.48e096c5.js" as="script" /><link rel="prefetch" href="/doc/assets/Vue3.html.324e646c.js" as="script" /><link rel="prefetch" href="/doc/assets/index.html.fb0ad0e0.js" as="script" /><link rel="prefetch" href="/doc/assets/第 1 章 导言.html.d6c662f8.js" as="script" /><link rel="prefetch" href="/doc/assets/第 2 章 TypeScript 概述.html.e976154a.js" as="script" /><link rel="prefetch" href="/doc/assets/第 3 章 类型全解.html.e4f1b931.js" as="script" /><link rel="prefetch" href="/doc/assets/第 4 章 函数.html.701a2968.js" as="script" /><link rel="prefetch" href="/doc/assets/第 5 章 类和接口.html.8988d546.js" as="script" /><link rel="prefetch" href="/doc/assets/第 6 章 类型进阶.html.45b313e3.js" as="script" /><link rel="prefetch" href="/doc/assets/index.html.a9dd6465.js" as="script" /><link rel="prefetch" href="/doc/assets/index.html.a3374cf8.js" as="script" /><link rel="prefetch" href="/doc/assets/面试题详解.html.c326eaaf.js" as="script" /><link rel="prefetch" href="/doc/assets/index.html.88582229.js" as="script" /><link rel="prefetch" href="/doc/assets/常见问题.html.e0f65550.js" as="script" /><link rel="prefetch" href="/doc/assets/扩展使用.html.87cccc41.js" as="script" /><link rel="prefetch" href="/doc/assets/掌握 GIT.html.c150b234.js" as="script" /><link rel="prefetch" href="/doc/assets/index.html.a3c2858b.js" as="script" /><link rel="prefetch" href="/doc/assets/面试题详解.html.9a53d157.js" as="script" /><link rel="prefetch" href="/doc/assets/index.html.101afd82.js" as="script" /><link rel="prefetch" href="/doc/assets/面试题详解.html.8224e1cd.js" as="script" /><link rel="prefetch" href="/doc/assets/index.html.54b5ca2d.js" as="script" /><link rel="prefetch" href="/doc/assets/基础掌握.html.d839cc53.js" as="script" /><link rel="prefetch" href="/doc/assets/index.html.80e4d5cc.js" as="script" /><link rel="prefetch" href="/doc/assets/基础掌握.html.9a178a04.js" as="script" /><link rel="prefetch" href="/doc/assets/扩展知识.html.3535ab30.js" as="script" /><link rel="prefetch" href="/doc/assets/项目搭建.html.e926587b.js" as="script" /><link rel="prefetch" href="/doc/assets/index.html.881e95b0.js" as="script" /><link rel="prefetch" href="/doc/assets/安装及使用.html.ba7314a3.js" as="script" /><link rel="prefetch" href="/doc/assets/index.html.f9509ce0.js" as="script" /><link rel="prefetch" href="/doc/assets/第 1 章.html.726a0bb9.js" as="script" /><link rel="prefetch" href="/doc/assets/第 2 章.html.38f55e7d.js" as="script" /><link rel="prefetch" href="/doc/assets/Module.html.3849b10b.js" as="script" /><link rel="prefetch" href="/doc/assets/Providers.html.7d2793f1.js" as="script" /><link rel="prefetch" href="/doc/assets/404.html.c5de7dd9.js" as="script" /><link rel="prefetch" href="/doc/assets/index.html.86b08b0b.js" as="script" /><link rel="prefetch" href="/doc/assets/index.html.f4119260.js" as="script" /><link rel="prefetch" href="/doc/assets/Vue2.html.caf7eb18.js" as="script" /><link rel="prefetch" href="/doc/assets/Vue3.html.6dc23cf4.js" as="script" /><link rel="prefetch" href="/doc/assets/index.html.868f2c80.js" as="script" /><link rel="prefetch" href="/doc/assets/第 1 章 导言.html.9edf000e.js" as="script" /><link rel="prefetch" href="/doc/assets/第 2 章 TypeScript 概述.html.76b27e4d.js" as="script" /><link rel="prefetch" href="/doc/assets/第 3 章 类型全解.html.9ad8a3d4.js" as="script" /><link rel="prefetch" href="/doc/assets/第 4 章 函数.html.9115df00.js" as="script" /><link rel="prefetch" href="/doc/assets/第 5 章 类和接口.html.e392a0d1.js" as="script" /><link rel="prefetch" href="/doc/assets/第 6 章 类型进阶.html.1b5b864e.js" as="script" /><link rel="prefetch" href="/doc/assets/index.html.e5a75968.js" as="script" /><link rel="prefetch" href="/doc/assets/index.html.974654cf.js" as="script" /><link rel="prefetch" href="/doc/assets/面试题详解.html.ed3fa7a3.js" as="script" /><link rel="prefetch" href="/doc/assets/index.html.3b9ebcaa.js" as="script" /><link rel="prefetch" href="/doc/assets/常见问题.html.b427e39a.js" as="script" /><link rel="prefetch" href="/doc/assets/扩展使用.html.76b3dd90.js" as="script" /><link rel="prefetch" href="/doc/assets/掌握 GIT.html.724416fc.js" as="script" /><link rel="prefetch" href="/doc/assets/index.html.8b55f9ef.js" as="script" /><link rel="prefetch" href="/doc/assets/面试题详解.html.8ee968a7.js" as="script" /><link rel="prefetch" href="/doc/assets/index.html.06371751.js" as="script" /><link rel="prefetch" href="/doc/assets/面试题详解.html.6b672044.js" as="script" /><link rel="prefetch" href="/doc/assets/index.html.b200eaff.js" as="script" /><link rel="prefetch" href="/doc/assets/基础掌握.html.5135d2c4.js" as="script" /><link rel="prefetch" href="/doc/assets/index.html.557b7bf5.js" as="script" /><link rel="prefetch" href="/doc/assets/基础掌握.html.7b535b09.js" as="script" /><link rel="prefetch" href="/doc/assets/扩展知识.html.c6b233af.js" as="script" /><link rel="prefetch" href="/doc/assets/项目搭建.html.450f0b1d.js" as="script" /><link rel="prefetch" href="/doc/assets/index.html.6483ed06.js" as="script" /><link rel="prefetch" href="/doc/assets/安装及使用.html.b4d859f3.js" as="script" /><link rel="prefetch" href="/doc/assets/index.html.f15cf3e9.js" as="script" /><link rel="prefetch" href="/doc/assets/第 1 章.html.127b1e7c.js" as="script" /><link rel="prefetch" href="/doc/assets/第 2 章.html.ea8e67e2.js" as="script" /><link rel="prefetch" href="/doc/assets/Module.html.f102db2a.js" as="script" /><link rel="prefetch" href="/doc/assets/Providers.html.9bef3753.js" as="script" /><link rel="prefetch" href="/doc/assets/404.html.2cfd6b20.js" as="script" /><link rel="prefetch" href="/doc/assets/photoswipe.esm.09e03fed.js" as="script" />
  </head>
  <body>
    <div id="app"><!--[--><!--[--><!--[--><span tabindex="-1"></span><a href="#main-content" class="skip-link sr-only">Skip to content</a><!--]--><div class="theme-container has-toc"><!--[--><!--[--><header class="navbar"><div class="navbar-left"><button class="toggle-sidebar-button" title="Toggle Sidebar"><span class="icon"></span></button><!--[--><!----><!--]--><a href="/doc/" class="brand"><!----><!----><span class="site-name">AT 的文档库</span></a><!--[--><!----><!--]--></div><div class="navbar-center"><!--[--><!----><!--]--><nav class="nav-links"><div class="nav-item hide-in-mobile"><a href="/doc/" class="nav-link" aria-label="首页"><!---->首页<!----></a></div><div class="nav-item hide-in-mobile"><div class="dropdown-wrapper"><button class="dropdown-title" type="button" aria-label="开发问题汇总"><span class="title"><!---->开发问题汇总</span><span class="arrow"></span><ul class="nav-dropdown"><li class="dropdown-item"><a href="/doc/development-question/Vue" class="nav-link" aria-label="Vue"><!---->Vue<!----></a></li></ul></button></div></div><div class="nav-item hide-in-mobile"><div class="dropdown-wrapper"><button class="dropdown-title" type="button" aria-label="系统笔记"><span class="title"><!---->系统笔记</span><span class="arrow"></span><ul class="nav-dropdown"><li class="dropdown-item"><a href="/doc/sysnotes/Git/%E6%8E%8C%E6%8F%A1%20GIT.html" class="nav-link" aria-label="GIT"><!---->GIT<!----></a></li><li class="dropdown-item"><a href="/doc/sysnotes/Nvm/%E5%AE%89%E8%A3%85%E5%8F%8A%E4%BD%BF%E7%94%A8.html" class="nav-link" aria-label="NVM"><!---->NVM<!----></a></li><li class="dropdown-item"><a href="/doc/sysnotes/Linux/%E5%9F%BA%E7%A1%80%E6%8E%8C%E6%8F%A1.html" class="nav-link" aria-label="Linux"><!---->Linux<!----></a></li><li class="dropdown-item"><a href="/doc/sysnotes/JavaScript" class="nav-link" aria-label="JavaScript"><!---->JavaScript<!----></a></li><li class="dropdown-item"><a href="/doc/sysnotes/CSS" class="nav-link" aria-label="CSS"><!---->CSS<!----></a></li><li class="dropdown-item"><a href="/doc/sysnotes/HTML" class="nav-link" aria-label="HTML"><!---->HTML<!----></a></li></ul></button></div></div><div class="nav-item hide-in-mobile"><div class="dropdown-wrapper"><button class="dropdown-title" type="button" aria-label="阅读笔记"><span class="title"><!---->阅读笔记</span><span class="arrow"></span><ul class="nav-dropdown"><li class="dropdown-item"><a href="/doc/readbook/《Vue.js 设计与实现》/" class="nav-link" aria-label="《Vue.js 设计与实现》"><!---->《Vue.js 设计与实现》<!----></a></li><li class="dropdown-item"><a href="/doc/readbook/《TypeScript 编程》/" class="nav-link" aria-label="《TypeScript 编程》"><!---->《TypeScript 编程》<!----></a></li></ul></button></div></div></nav><!--[--><!----><!--]--></div><div class="navbar-right"><!--[--><!----><!--]--><div class="nav-item hide-in-mobile"><button id="appearance-switch"><svg xmlns="http://www.w3.org/2000/svg" class="icon auto-icon" viewBox="0 0 1024 1024" fill="currentColor" aria-label="auto icon" style="display:block;"><path d="M512 992C246.92 992 32 777.08 32 512S246.92 32 512 32s480 214.92 480 480-214.92 480-480 480zm0-840c-198.78 0-360 161.22-360 360 0 198.84 161.22 360 360 360s360-161.16 360-360c0-198.78-161.22-360-360-360zm0 660V212c165.72 0 300 134.34 300 300 0 165.72-134.28 300-300 300z"></path></svg><svg xmlns="http://www.w3.org/2000/svg" class="icon dark-icon" viewBox="0 0 1024 1024" fill="currentColor" aria-label="dark icon" style="display:none;"><path d="M524.8 938.667h-4.267a439.893 439.893 0 0 1-313.173-134.4 446.293 446.293 0 0 1-11.093-597.334A432.213 432.213 0 0 1 366.933 90.027a42.667 42.667 0 0 1 45.227 9.386 42.667 42.667 0 0 1 10.24 42.667 358.4 358.4 0 0 0 82.773 375.893 361.387 361.387 0 0 0 376.747 82.774 42.667 42.667 0 0 1 54.187 55.04 433.493 433.493 0 0 1-99.84 154.88 438.613 438.613 0 0 1-311.467 128z"></path></svg><svg xmlns="http://www.w3.org/2000/svg" class="icon light-icon" viewBox="0 0 1024 1024" fill="currentColor" aria-label="light icon" style="display:none;"><path d="M952 552h-80a40 40 0 0 1 0-80h80a40 40 0 0 1 0 80zM801.88 280.08a41 41 0 0 1-57.96-57.96l57.96-58a41.04 41.04 0 0 1 58 58l-58 57.96zM512 752a240 240 0 1 1 0-480 240 240 0 0 1 0 480zm0-560a40 40 0 0 1-40-40V72a40 40 0 0 1 80 0v80a40 40 0 0 1-40 40zm-289.88 88.08-58-57.96a41.04 41.04 0 0 1 58-58l57.96 58a41 41 0 0 1-57.96 57.96zM192 512a40 40 0 0 1-40 40H72a40 40 0 0 1 0-80h80a40 40 0 0 1 40 40zm30.12 231.92a41 41 0 0 1 57.96 57.96l-57.96 58a41.04 41.04 0 0 1-58-58l58-57.96zM512 832a40 40 0 0 1 40 40v80a40 40 0 0 1-80 0v-80a40 40 0 0 1 40-40zm289.88-88.08 58 57.96a41.04 41.04 0 0 1-58 58l-57.96-58a41 41 0 0 1 57.96-57.96z"></path></svg></button></div><form class="search-box" role="search"><input type="search" autocomplete="off" spellcheck="false" value><!----></form><!--[--><!----><!--]--><button class="toggle-navbar-button" aria-label="Toggle Navbar" aria-expanded="false" aria-controls="nav-screen"><span class="button-container"><span class="button-top"></span><span class="button-middle"></span><span class="button-bottom"></span></span></button></div></header><!----><!--]--><!----><div class="toggle-sidebar-wrapper"><span class="arrow left"></span></div><aside class="sidebar"><!--[--><!----><!--]--><ul class="sidebar-links"><li><section class="sidebar-group"><button class="sidebar-heading clickable"><!----><span class="title">CSS</span><span class="arrow right"></span></button><!----></section></li><li><section class="sidebar-group"><button class="sidebar-heading clickable"><!----><span class="title">GIT</span><span class="arrow right"></span></button><!----></section></li><li><section class="sidebar-group"><button class="sidebar-heading clickable"><!----><span class="title">HTML</span><span class="arrow right"></span></button><!----></section></li><li><section class="sidebar-group"><button class="sidebar-heading clickable"><!----><span class="title">JavaScript</span><span class="arrow right"></span></button><!----></section></li><li><section class="sidebar-group"><button class="sidebar-heading clickable"><!----><span class="title">Linux</span><span class="arrow right"></span></button><!----></section></li><li><section class="sidebar-group"><button class="sidebar-heading clickable"><!----><span class="title">NestJs</span><span class="arrow right"></span></button><!----></section></li><li><section class="sidebar-group"><button class="sidebar-heading clickable"><!----><span class="title">NVM</span><span class="arrow right"></span></button><!----></section></li></ul><!--[--><!----><!--]--></aside><!--[--><main class="page" id="main-content"><!--[--><!----><nav class="breadcrumb disable"></nav><div class="page-title"><h1><!---->控制器</h1><div class="page-info"><!----><!----><span class="date-info" aria-label="写作日期📅" data-balloon-pos="down"><svg xmlns="http://www.w3.org/2000/svg" class="icon calendar-icon" viewBox="0 0 1024 1024" fill="currentColor" aria-label="calendar icon"><path d="M716.4 110.137c0-18.753-14.72-33.473-33.472-33.473-18.753 0-33.473 14.72-33.473 33.473v33.473h66.993v-33.473zm-334.87 0c0-18.753-14.72-33.473-33.473-33.473s-33.52 14.72-33.52 33.473v33.473h66.993v-33.473zm468.81 33.52H716.4v100.465c0 18.753-14.72 33.473-33.472 33.473a33.145 33.145 0 01-33.473-33.473V143.657H381.53v100.465c0 18.753-14.72 33.473-33.473 33.473a33.145 33.145 0 01-33.473-33.473V143.657H180.6A134.314 134.314 0 0046.66 277.595v535.756A134.314 134.314 0 00180.6 947.289h669.74a134.36 134.36 0 00133.94-133.938V277.595a134.314 134.314 0 00-133.94-133.938zm33.473 267.877H147.126a33.145 33.145 0 01-33.473-33.473c0-18.752 14.72-33.473 33.473-33.473h736.687c18.752 0 33.472 14.72 33.472 33.473a33.145 33.145 0 01-33.472 33.473z"></path></svg><span>2023年2月19日</span><meta property="datePublished" content="2023-02-19T11:39:44.000Z"></span><!----><!----><span class="reading-time-info" aria-label="阅读时间⌛" data-balloon-pos="down"><svg xmlns="http://www.w3.org/2000/svg" class="icon timer-icon" viewBox="0 0 1024 1024" fill="currentColor" aria-label="timer icon"><path d="M799.387 122.15c4.402-2.978 7.38-7.897 7.38-13.463v-1.165c0-8.933-7.38-16.312-16.312-16.312H256.33c-8.933 0-16.311 7.38-16.311 16.312v1.165c0 5.825 2.977 10.874 7.637 13.592 4.143 194.44 97.22 354.963 220.201 392.763-122.204 37.542-214.893 196.511-220.2 389.397-4.661 5.049-7.638 11.651-7.638 19.03v5.825h566.49v-5.825c0-7.379-2.849-13.981-7.509-18.9-5.049-193.016-97.867-351.985-220.2-389.527 123.24-37.67 216.446-198.453 220.588-392.892zM531.16 450.445v352.632c117.674 1.553 211.787 40.778 211.787 88.676H304.097c0-48.286 95.149-87.382 213.728-88.676V450.445c-93.077-3.107-167.901-81.297-167.901-177.093 0-8.803 6.99-15.793 15.793-15.793 8.803 0 15.794 6.99 15.794 15.793 0 80.261 63.69 145.635 142.01 145.635s142.011-65.374 142.011-145.635c0-8.803 6.99-15.793 15.794-15.793s15.793 6.99 15.793 15.793c0 95.019-73.789 172.82-165.96 177.093z"></path></svg><span>大约 9 分钟</span><meta property="timeRequired" content="PT9M"></span></div><hr></div><div class="toc-place-holder"><aside id="toc"><div class="toc-header">此页内容</div><div class="toc-wrapper"><ul class="toc-list"><!--[--><li class="toc-item"><a aria-current="page" href="/doc/sysnotes/NestJs/%E6%A6%82%E8%BF%B0/Controllers.html#路由" class="router-link-active router-link-exact-active toc-link level2">路由</a></li><!----><!--]--><!--[--><li class="toc-item"><a aria-current="page" href="/doc/sysnotes/NestJs/%E6%A6%82%E8%BF%B0/Controllers.html#request" class="router-link-active router-link-exact-active toc-link level2">Request</a></li><!----><!--]--><!--[--><li class="toc-item"><a aria-current="page" href="/doc/sysnotes/NestJs/%E6%A6%82%E8%BF%B0/Controllers.html#资源" class="router-link-active router-link-exact-active toc-link level2">资源</a></li><!----><!--]--><!--[--><li class="toc-item"><a aria-current="page" href="/doc/sysnotes/NestJs/%E6%A6%82%E8%BF%B0/Controllers.html#路由通配符" class="router-link-active router-link-exact-active toc-link level2">路由通配符</a></li><!----><!--]--><!--[--><li class="toc-item"><a aria-current="page" href="/doc/sysnotes/NestJs/%E6%A6%82%E8%BF%B0/Controllers.html#状态码" class="router-link-active router-link-exact-active toc-link level2">状态码</a></li><!----><!--]--><!--[--><li class="toc-item"><a aria-current="page" href="/doc/sysnotes/NestJs/%E6%A6%82%E8%BF%B0/Controllers.html#headers" class="router-link-active router-link-exact-active toc-link level2">Headers</a></li><!----><!--]--><!--[--><li class="toc-item"><a aria-current="page" href="/doc/sysnotes/NestJs/%E6%A6%82%E8%BF%B0/Controllers.html#重定向" class="router-link-active router-link-exact-active toc-link level2">重定向</a></li><!----><!--]--><!--[--><li class="toc-item"><a aria-current="page" href="/doc/sysnotes/NestJs/%E6%A6%82%E8%BF%B0/Controllers.html#路由参数" class="router-link-active router-link-exact-active toc-link level2">路由参数</a></li><!----><!--]--><!--[--><li class="toc-item"><a aria-current="page" href="/doc/sysnotes/NestJs/%E6%A6%82%E8%BF%B0/Controllers.html#子路由" class="router-link-active router-link-exact-active toc-link level2">子路由</a></li><!----><!--]--><!--[--><li class="toc-item"><a aria-current="page" href="/doc/sysnotes/NestJs/%E6%A6%82%E8%BF%B0/Controllers.html#作用域" class="router-link-active router-link-exact-active toc-link level2">作用域</a></li><!----><!--]--><!--[--><li class="toc-item"><a aria-current="page" href="/doc/sysnotes/NestJs/%E6%A6%82%E8%BF%B0/Controllers.html#异步性" class="router-link-active router-link-exact-active toc-link level2">异步性</a></li><!----><!--]--><!--[--><li class="toc-item"><a aria-current="page" href="/doc/sysnotes/NestJs/%E6%A6%82%E8%BF%B0/Controllers.html#请求负载" class="router-link-active router-link-exact-active toc-link level2">请求负载</a></li><!----><!--]--><!--[--><li class="toc-item"><a aria-current="page" href="/doc/sysnotes/NestJs/%E6%A6%82%E8%BF%B0/Controllers.html#处理错误" class="router-link-active router-link-exact-active toc-link level2">处理错误</a></li><!----><!--]--><!--[--><li class="toc-item"><a aria-current="page" href="/doc/sysnotes/NestJs/%E6%A6%82%E8%BF%B0/Controllers.html#完整示例" class="router-link-active router-link-exact-active toc-link level2">完整示例</a></li><!----><!--]--><!--[--><li class="toc-item"><a aria-current="page" href="/doc/sysnotes/NestJs/%E6%A6%82%E8%BF%B0/Controllers.html#最后一步" class="router-link-active router-link-exact-active toc-link level2">最后一步</a></li><!----><!--]--><!--[--><li class="toc-item"><a aria-current="page" href="/doc/sysnotes/NestJs/%E6%A6%82%E8%BF%B0/Controllers.html#类库特有方式" class="router-link-active router-link-exact-active toc-link level2">类库特有方式</a></li><!----><!--]--></ul></div></aside></div><!----><div class="theme-hope-content"><h1 id="控制器" tabindex="-1"><a class="header-anchor" href="#控制器" aria-hidden="true">#</a> 控制器</h1><p>控制器负责处理传入的<strong>请求</strong>和客户端返回的<strong>响应</strong>。</p><p><img src="https://docs.nestjs.com/assets/Controllers_1.png" alt="控制器"></p><p>控制器的目的是接收应用特定请求。<strong>路由</strong>机制控制哪个控制器接收哪些请求。通常，每个控制器有多个路由，不用的路由可以执行不同的操作。</p><p>创建一个基本控制器，使用类和<code>装饰器</code>。装饰器将类与所需的元数据相关联，并使 Nest 能够创建路由映射（将请求绑定到相应的控制器）</p><h2 id="路由" tabindex="-1"><a class="header-anchor" href="#路由" aria-hidden="true">#</a> 路由</h2><p>下面使用 <code>@Controller()</code> 装饰器定义一个基本控制器。可选路由路径前缀设置为 <code>user</code>。在 <code>@Controller()</code> 装饰器中使用路径前缀可以轻松的对一组相关的路由进行分组，并最大程度的减少重复代码。</p><div class="language-typescript line-numbers-mode" data-ext="ts"><pre class="language-typescript"><code><span class="token doc-comment comment">/**
 * user.controller.ts
 */</span>
<span class="token keyword">import</span> <span class="token punctuation">{</span>Controller<span class="token punctuation">,</span>Get<span class="token punctuation">}</span> <span class="token keyword">from</span> <span class="token string">&#39;@nestjs/common&#39;</span>

<span class="token decorator"><span class="token at operator">@</span><span class="token function">Controller</span></span><span class="token punctuation">(</span><span class="token string">&#39;user&#39;</span><span class="token punctuation">)</span>
<span class="token keyword">export</span> <span class="token keyword">class</span> <span class="token class-name">UserController</span> <span class="token punctuation">{</span>
    <span class="token decorator"><span class="token at operator">@</span><span class="token function">Get</span></span><span class="token punctuation">(</span><span class="token string">&#39;list&#39;</span><span class="token punctuation">)</span>
    <span class="token function">findAll</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">{</span>
        <span class="token keyword">return</span> <span class="token string">&#39;user findAll&#39;</span>
    <span class="token punctuation">}</span>
<span class="token punctuation">}</span>
</code></pre><div class="line-numbers" aria-hidden="true"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><blockquote><p>可以使用 CLI 创建控制器，只需要使用 <code>nest g controller user</code> 命令即可。</p></blockquote><p><code>findAll()</code> 方法之前的 <code>@Get()</code> HTTP 请求方法装饰器告诉 Nest 为 HTTP 请求的特定端点创建处理程序。端点对应于 HTTP 请求方法（在本例中为 GET）和路由路径（如 <code>GET /user</code>）。一个处理程序的路由路径是通过连接为控制器（Controller）声明的（可选）前缀和请求装饰器中指定的任何路径来确定。</p><p>Nest 使用两种不同的操作响应选项的概念：</p><table><thead><tr><th>概念</th><th>解释</th></tr></thead><tbody><tr><td>标准（推荐）</td><td>使用这个内置方法，当请求处理程序返回一个 <code>JavaScript</code> 对象或数组时，它将自动序列化为 <code>Json</code>。但是当返回基本类型时（string,number,boolean）时，<code>Nest</code> 只发送值，而不尝试序列化。</td></tr><tr><td>类库特有的</td><td>可以在函数签名处通过 <code>@Res()</code> 注入类库特定的响应对象（如：<code>Express</code>）。使用此方法，能使用由该对象暴露的原生响应处理函数。如使用 <code>Express</code>,可以使用 <code>response.status(200).send()</code> 构建响应</td></tr></tbody></table><div class="custom-container danger"><p class="custom-container-title">注意</p><p>Nest 检测处理程序何时使用 <code>Res()</code> 或 <code>Next()</code>，表名选择了特定与库的选项。如果在一个处理函数上同时使用了这两个方法，那么此处的标准方式就是自动禁用此路由，将不会得到想要的结果。如果需要在某个处理函数上同时使用这两种方法（如：通过注入响应对象，单独设置 cookie/header，但把其余部分留给框架），必须在装饰器 <code>@Res({passthrough: true})</code> 将 <code>passthrough</code> 设置为 <code>true</code></p></div><h2 id="request" tabindex="-1"><a class="header-anchor" href="#request" aria-hidden="true">#</a> Request</h2><p>处理程序又是需要访问客户端<strong>请求</strong>细节。Nest 提供了对帝城平台（默认 <code>Express</code>）的请求对象（request）的访问方式。我们可以在处理函数的签名中使用 <code>@Req()</code> 装饰器，指示 Nest 将请求对象注入处理程序。</p><div class="language-typescript line-numbers-mode" data-ext="ts"><pre class="language-typescript"><code><span class="token keyword">import</span> <span class="token punctuation">{</span>Controller<span class="token punctuation">,</span>Req<span class="token punctuation">,</span>Get<span class="token punctuation">}</span> <span class="token keyword">from</span> <span class="token string">&#39;@nestjs/common&#39;</span>
<span class="token keyword">import</span> <span class="token punctuation">{</span> Request <span class="token punctuation">}</span> <span class="token keyword">from</span> <span class="token string">&#39;express&#39;</span><span class="token punctuation">;</span>

<span class="token decorator"><span class="token at operator">@</span><span class="token function">Controller</span></span><span class="token punctuation">(</span><span class="token string">&#39;user&#39;</span><span class="token punctuation">)</span>
<span class="token keyword">export</span> <span class="token keyword">class</span> <span class="token class-name">UserController</span><span class="token punctuation">{</span>
    <span class="token decorator"><span class="token at operator">@</span><span class="token function">Get</span></span><span class="token punctuation">(</span><span class="token punctuation">)</span>
    <span class="token function">findAll</span><span class="token punctuation">(</span><span class="token decorator"><span class="token at operator">@</span><span class="token function">Req</span></span><span class="token punctuation">(</span><span class="token punctuation">)</span> req<span class="token operator">:</span>Request<span class="token punctuation">)</span><span class="token operator">:</span><span class="token builtin">string</span><span class="token punctuation">{</span>
        <span class="token keyword">return</span> <span class="token string">&#39;xxxxxx&#39;</span>
    <span class="token punctuation">}</span>
<span class="token punctuation">}</span>
</code></pre><div class="line-numbers" aria-hidden="true"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><div class="custom-container tip"><p class="custom-container-title">提示</p><p>为了在 <code>express</code> 中使用 <code>TypeScript</code> (如：<code>req:Request</code> 上面的参数实例)，需要安装 <code>@types/express</code></p></div><p><code>Request</code> 对象代表 HTTP 请求，并具有查询字符串，请求参数，HTTP 标头（HTTP header）和正文（HTTP body）的属性。在多数情况下，不必手动获取。可以使用专用的装饰器</p><table><thead><tr><th>装饰器</th><th>解析</th></tr></thead><tbody><tr><td>@Request(),@Req()</td><td>req</td></tr><tr><td>@Response(),@Res()*</td><td>res</td></tr><tr><td>@Next()</td><td>next</td></tr><tr><td>@Session()</td><td>req.session</td></tr><tr><td>@Param(key:string)</td><td>req.params/req.params[key]</td></tr><tr><td>@Body(key:string)</td><td>req.body/req.body[key]</td></tr><tr><td>@Query(key:string)</td><td>req.query/req.query[key]</td></tr><tr><td>@Headers(name:string)</td><td>req,headers/req.headers[name]</td></tr><tr><td>@Ip()</td><td>req.ip</td></tr><tr><td>@HostParam()</td><td>req.hosts</td></tr></tbody></table><p>为了与底层 HTTP 平台（如：Express 和 Fastofy）之间的类型兼容，Nest 提供 <code>@Res()</code> 和 <code>@Response()</code> 装饰器。 <code>@Res()</code> 是 <code>@Response()</code> 的别名。两者都直接暴露了底层平台的 <code>response</code> 对象接口。需要注意的是，在请求处理函数中注入 <code>@Res()</code> 或 <code>@Response()</code> 时，将会 Nest 置于该处理函数的<strong>特定于库</strong>（Library-specific mode）的模式下，并负责管理响应。这样做时，必须通过调用 <code>response</code> 对象（例如：<code>res.json()</code> 或 ```` res.send() ```）发出某种响应，否则 HTTP 服务将会被挂起。</p><h2 id="资源" tabindex="-1"><a class="header-anchor" href="#资源" aria-hidden="true">#</a> 资源</h2><p>创建 <strong>POST</strong> 处理程序：</p><div class="language-typescript line-numbers-mode" data-ext="ts"><pre class="language-typescript"><code><span class="token doc-comment comment">/**
 * user.controller.ts
 */</span>

<span class="token keyword">import</span> <span class="token punctuation">{</span>Controller<span class="token punctuation">,</span>Post<span class="token punctuation">}</span> <span class="token keyword">from</span> <span class="token string">&#39;@nestjs/common&#39;</span>

<span class="token decorator"><span class="token at operator">@</span><span class="token function">Controller</span></span><span class="token punctuation">(</span><span class="token string">&#39;user&#39;</span><span class="token punctuation">)</span>
<span class="token keyword">export</span> <span class="token keyword">class</span> <span class="token class-name">UserController</span> <span class="token punctuation">{</span>
    <span class="token decorator"><span class="token at operator">@</span><span class="token function">Post</span></span><span class="token punctuation">(</span><span class="token punctuation">)</span>
    <span class="token function">create</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token operator">:</span><span class="token builtin">string</span><span class="token punctuation">{</span>
        <span class="token keyword">return</span> <span class="token string">&#39;create&#39;</span>
    <span class="token punctuation">}</span>
<span class="token punctuation">}</span>
</code></pre><div class="line-numbers" aria-hidden="true"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>Nest 为所有标准的 HTTP 方法提供相应的装饰器。<code>@Put(),@Delete(),@Patch(),@Options(),@Head()</code>。<code>@All()</code> 则用于定义一个用于处理所有 HTTP 请求方法的处理程序。</p><h2 id="路由通配符" tabindex="-1"><a class="header-anchor" href="#路由通配符" aria-hidden="true">#</a> 路由通配符</h2><p>路有同样支持模式匹配。例如，型号被用作通配符，将匹配任何字符组合。</p><div class="language-typescript line-numbers-mode" data-ext="ts"><pre class="language-typescript"><code>  <span class="token decorator"><span class="token at operator">@</span><span class="token function">Get</span></span><span class="token punctuation">(</span><span class="token string">&#39;ab*cd&#39;</span><span class="token punctuation">)</span>
  <span class="token function">find</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
    <span class="token keyword">return</span> <span class="token string">&#39;find&#39;</span>
  <span class="token punctuation">}</span>
</code></pre><div class="line-numbers" aria-hidden="true"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>路由路径 <code>ab*cd</code> 将匹配 <code>abcd,ab_cd,abecd</code> 等。字符 <code>?，+，*，()</code> 是他们的正则表达式对应项的子集。连字符（-）和（.）按字符串路逐字解析。</p><h2 id="状态码" tabindex="-1"><a class="header-anchor" href="#状态码" aria-hidden="true">#</a> 状态码</h2><p>默认情况下，响应<strong>状态码</strong>为 <strong>200</strong>,除了 POST 请求（默认为 201），可以通过在处理函数外添加 <code>@HttpCode()</code> 装饰器来轻松更改此行为。</p><div class="language-typescript line-numbers-mode" data-ext="ts"><pre class="language-typescript"><code>  <span class="token decorator"><span class="token at operator">@</span><span class="token function">Post</span></span><span class="token punctuation">(</span><span class="token punctuation">)</span>
  <span class="token decorator"><span class="token at operator">@</span><span class="token function">HttpCode</span></span><span class="token punctuation">(</span><span class="token number">204</span><span class="token punctuation">)</span>
  <span class="token function">create</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token operator">:</span> <span class="token builtin">string</span> <span class="token punctuation">{</span>
    <span class="token keyword">return</span> <span class="token string">&#39;create&#39;</span>
  <span class="token punctuation">}</span>
</code></pre><div class="line-numbers" aria-hidden="true"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><h2 id="headers" tabindex="-1"><a class="header-anchor" href="#headers" aria-hidden="true">#</a> Headers</h2><p>要制定自定义响应头，可以使用 <code>@Header()</code> 装饰器或类库特有的响应对象，（并直接调用 res.header()）。</p><div class="language-typescript line-numbers-mode" data-ext="ts"><pre class="language-typescript"><code>  <span class="token decorator"><span class="token at operator">@</span><span class="token function">Post</span></span><span class="token punctuation">(</span><span class="token punctuation">)</span>
  <span class="token decorator"><span class="token at operator">@</span><span class="token function">HttpCode</span></span><span class="token punctuation">(</span><span class="token number">204</span><span class="token punctuation">)</span>
  <span class="token decorator"><span class="token at operator">@</span><span class="token function">Header</span></span><span class="token punctuation">(</span><span class="token string">&#39;Cache-Control&#39;</span><span class="token punctuation">,</span> <span class="token string">&#39;none&#39;</span><span class="token punctuation">)</span>
  <span class="token function">create</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token operator">:</span> <span class="token builtin">string</span> <span class="token punctuation">{</span>
    <span class="token keyword">return</span> <span class="token string">&#39;create&#39;</span>
  <span class="token punctuation">}</span>
</code></pre><div class="line-numbers" aria-hidden="true"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><h2 id="重定向" tabindex="-1"><a class="header-anchor" href="#重定向" aria-hidden="true">#</a> 重定向</h2><p>要将响应重定向发到特定的 <code>URL</code>，可以使用 <code>@Redirect()</code> 装饰器或特定与类库的响应对象（``` res.redirect() ````）。</p><p><code>@Redirect()</code> 装饰器有两个可选参数，<code>url</code> 和 <code>statusCode</code>。如果省略，则 <code>statusCode</code> 默认为 302。</p><div class="language-typescript line-numbers-mode" data-ext="ts"><pre class="language-typescript"><code>  <span class="token decorator"><span class="token at operator">@</span><span class="token function">Get</span></span><span class="token punctuation">(</span><span class="token punctuation">)</span>
  <span class="token decorator"><span class="token at operator">@</span><span class="token function">Redirect</span></span><span class="token punctuation">(</span><span class="token string">&#39;https://www.baidu.com&#39;</span><span class="token punctuation">,</span> <span class="token number">302</span><span class="token punctuation">)</span>
</code></pre><div class="line-numbers" aria-hidden="true"><div class="line-number"></div><div class="line-number"></div></div></div><p>动态决定 HTTP 状态码或 URL。通过路由处理方法返回一个如下格式对象：</p><div class="language-json line-numbers-mode" data-ext="json"><pre class="language-json"><code><span class="token punctuation">{</span>
    <span class="token property">&quot;url&quot;</span><span class="token operator">:</span><span class="token string">&quot;string&quot;</span><span class="token punctuation">,</span>
    <span class="token property">&quot;statusCode&quot;</span><span class="token operator">:</span><span class="token number">302</span>
<span class="token punctuation">}</span>
</code></pre><div class="line-numbers" aria-hidden="true"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>返回的值将覆盖传递给 <code>@Redirect()</code> 装饰器的所有参数：</p><div class="language-typescript line-numbers-mode" data-ext="ts"><pre class="language-typescript"><code>  <span class="token decorator"><span class="token at operator">@</span><span class="token function">Get</span></span><span class="token punctuation">(</span><span class="token punctuation">)</span>
  <span class="token decorator"><span class="token at operator">@</span><span class="token function">Redirect</span></span><span class="token punctuation">(</span><span class="token string">&#39;https://www.baidu.com&#39;</span><span class="token punctuation">,</span> <span class="token number">302</span><span class="token punctuation">)</span>
  <span class="token function">getDocs</span><span class="token punctuation">(</span><span class="token decorator"><span class="token at operator">@</span><span class="token function">Query</span></span><span class="token punctuation">(</span><span class="token string">&#39;version&#39;</span><span class="token punctuation">)</span> version<span class="token punctuation">)</span><span class="token punctuation">{</span>
    <span class="token keyword">if</span><span class="token punctuation">(</span>version<span class="token operator">&amp;&amp;</span>version<span class="token operator">===</span><span class="token string">&#39;5&#39;</span><span class="token punctuation">)</span><span class="token punctuation">{</span>
        <span class="token keyword">return</span> <span class="token punctuation">{</span>
            url<span class="token operator">:</span><span class="token string">&#39;https://docs.nestjs.com/v5/&#39;</span><span class="token punctuation">,</span>
            statusCode<span class="token operator">:</span><span class="token number">302</span>
        <span class="token punctuation">}</span>
    <span class="token punctuation">}</span>
  <span class="token punctuation">}</span>
</code></pre><div class="line-numbers" aria-hidden="true"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><h2 id="路由参数" tabindex="-1"><a class="header-anchor" href="#路由参数" aria-hidden="true">#</a> 路由参数</h2><p>需要接受<strong>动态数据</strong>（dynamic data）作为请求的一部分是（例如：使用 <code>GET user/1</code> 来获取 id 为 1 的用户），带有静态路径的路由将无法工作。为了定义带参数的路由，可以在路由路径中添加路由参数<strong>标记</strong>（token）以捕获请求 URL 中该位置的动态值。</p><div class="language-typescript line-numbers-mode" data-ext="ts"><pre class="language-typescript"><code> <span class="token decorator"><span class="token at operator">@</span><span class="token function">Get</span></span><span class="token punctuation">(</span><span class="token string">&#39;:id&#39;</span><span class="token punctuation">)</span>
 <span class="token function">findOne</span><span class="token punctuation">(</span><span class="token decorator"><span class="token at operator">@</span><span class="token function">Param</span></span><span class="token punctuation">(</span><span class="token punctuation">)</span> params<span class="token punctuation">)</span><span class="token punctuation">{</span>
    <span class="token keyword">return</span> params<span class="token punctuation">.</span>id
 <span class="token punctuation">}</span>
 <span class="token comment">// 或</span>
 <span class="token function">findOne</span><span class="token punctuation">(</span><span class="token decorator"><span class="token at operator">@</span><span class="token function">Param</span></span><span class="token punctuation">(</span><span class="token string">&#39;id&#39;</span><span class="token punctuation">)</span> id<span class="token punctuation">)</span><span class="token punctuation">{</span>
    <span class="token keyword">return</span> id
 <span class="token punctuation">}</span>
</code></pre><div class="line-numbers" aria-hidden="true"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><h2 id="子路由" tabindex="-1"><a class="header-anchor" href="#子路由" aria-hidden="true">#</a> 子路由</h2><p><code>@Controller()</code> 装饰器可以接受一个 <code>host</code> 选项，以要求传入请求的 <code>HTTP</code> 主机匹配某个特定值。</p><div class="language-typescript line-numbers-mode" data-ext="ts"><pre class="language-typescript"><code><span class="token decorator"><span class="token at operator">@</span><span class="token function">Controller</span></span><span class="token punctuation">(</span><span class="token punctuation">{</span>host<span class="token operator">:</span><span class="token string">&#39;admin.example.com&#39;</span><span class="token punctuation">}</span><span class="token punctuation">)</span>

<span class="token keyword">export</span> <span class="token keyword">class</span> <span class="token class-name">AdminController</span> <span class="token punctuation">{</span>
  <span class="token decorator"><span class="token at operator">@</span><span class="token function">Get</span></span><span class="token punctuation">(</span><span class="token punctuation">)</span>
  <span class="token function">index</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token operator">:</span><span class="token builtin">string</span><span class="token punctuation">{</span>
    <span class="token keyword">return</span> <span class="token string">&#39;xxx&#39;</span>
  <span class="token punctuation">}</span>
<span class="token punctuation">}</span>
</code></pre><div class="line-numbers" aria-hidden="true"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><div class="custom-container danger"><p class="custom-container-title">警告</p><p><strong>Fstify</strong> 缺乏对嵌套路由器的支持，因此当使用子域路由时，应该改用 <strong>Express</strong> 适配器。</p></div><p>与一个路由路径 <code>path</code> 类似，<code>hosts</code> 选项可以使用参数标识来捕获主机名中该位置的动态值。</p><div class="language-typescript line-numbers-mode" data-ext="ts"><pre class="language-typescript"><code><span class="token decorator"><span class="token at operator">@</span><span class="token function">Controller</span></span><span class="token punctuation">(</span><span class="token punctuation">{</span> host<span class="token operator">:</span> <span class="token string">&#39;:account.example.com&#39;</span> <span class="token punctuation">}</span><span class="token punctuation">)</span>
<span class="token keyword">export</span> <span class="token keyword">class</span> <span class="token class-name">AccountController</span> <span class="token punctuation">{</span>
  <span class="token decorator"><span class="token at operator">@</span><span class="token function">Get</span></span><span class="token punctuation">(</span><span class="token punctuation">)</span>
  <span class="token function">getInfo</span><span class="token punctuation">(</span><span class="token decorator"><span class="token at operator">@</span><span class="token function">HostParam</span></span><span class="token punctuation">(</span><span class="token string">&#39;account&#39;</span><span class="token punctuation">)</span> account<span class="token operator">:</span> <span class="token builtin">string</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
    <span class="token keyword">return</span> account<span class="token punctuation">;</span>
  <span class="token punctuation">}</span>
<span class="token punctuation">}</span>

</code></pre><div class="line-numbers" aria-hidden="true"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><h2 id="作用域" tabindex="-1"><a class="header-anchor" href="#作用域" aria-hidden="true">#</a> 作用域</h2><h2 id="异步性" tabindex="-1"><a class="header-anchor" href="#异步性" aria-hidden="true">#</a> 异步性</h2><p>数据读取（data extraction）大多是异步的.这就是为什么 Nest 完美支持异步函数（Async Function）特性的原因。</p><p>每个异步函数都必须返回一个 Promise。这意味着您可以返回延迟值，而 Nest 将自行解析它。让我们看看下面这个例子:</p><div class="language-typescript line-numbers-mode" data-ext="ts"><pre class="language-typescript"><code><span class="token decorator"><span class="token at operator">@</span><span class="token function">Get</span></span><span class="token punctuation">(</span><span class="token punctuation">)</span>
<span class="token keyword">async</span> <span class="token function">findAll</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token operator">:</span> <span class="token builtin">Promise</span><span class="token operator">&lt;</span><span class="token builtin">any</span><span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token operator">&gt;</span> <span class="token punctuation">{</span>
  <span class="token keyword">return</span> <span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>

</code></pre><div class="line-numbers" aria-hidden="true"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>这是完全有效的。此外，通过返回 RxJS observable 流，Nest 路由处理程序将更加强大。 Nest 将自动订阅下面的源并获取最后发出的值（在流完成后）。</p><h2 id="请求负载" tabindex="-1"><a class="header-anchor" href="#请求负载" aria-hidden="true">#</a> 请求负载</h2><p>此前我们列举的的 <code>POST</code> 路由处理程序样例中，处理程序没有接受任何客户端参数。我们在这里通过添加 <code>@Body()</code> 参数来解决这个问题。</p><p>首先（如果使用 TypeScript），我们需要确定 <code>DTO</code>（数据传输对象）模式。<code>DTO</code> 是一个对象，它定义了如何通过网络发送数据。我们可以通过使用 <strong>TypeScript</strong> 接口（Interface）或简单的类（Class）来定义 <code>DTO</code> 模式。推荐使用类。为什么？类是 JavaScript ES6 标准的一部分，因此它们在<strong>编译后</strong>的 JavaScript 中被保留为实际实体。另一方面，由于 TypeScript 接口在转换过程中被删除，所以 Nest 不能在运行时引用它们。这一点很重要，因为诸如管道（<strong>Pipe</strong>）之类的特性为在运行时访问变量的元类型提供更多的可能性。</p><div class="language-typescript line-numbers-mode" data-ext="ts"><pre class="language-typescript"><code><span class="token doc-comment comment">/**
 * create-user.dto.ts
 */</span>

<span class="token keyword">export</span> <span class="token keyword">class</span> <span class="token class-name">CreateUser</span><span class="token punctuation">{</span>
    <span class="token keyword">readonly</span> name<span class="token operator">:</span><span class="token builtin">string</span>
    <span class="token keyword">readonly</span> age<span class="token operator">:</span><span class="token builtin">number</span>
<span class="token punctuation">}</span>
</code></pre><div class="line-numbers" aria-hidden="true"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><div class="language-typescript line-numbers-mode" data-ext="ts"><pre class="language-typescript"><code><span class="token doc-comment comment">/**
 * user.controller.ts
 */</span>
<span class="token decorator"><span class="token at operator">@</span><span class="token function">Post</span></span><span class="token punctuation">(</span><span class="token punctuation">)</span>
<span class="token keyword">async</span> <span class="token function">create</span><span class="token punctuation">(</span><span class="token decorator"><span class="token at operator">@</span><span class="token function">Body</span></span><span class="token punctuation">(</span><span class="token punctuation">)</span> createCatDto<span class="token operator">:</span> CreateCatDto<span class="token punctuation">)</span> <span class="token punctuation">{</span>
  <span class="token keyword">return</span> <span class="token string">&#39;xxxx&#39;</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
</code></pre><div class="line-numbers" aria-hidden="true"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><h2 id="处理错误" tabindex="-1"><a class="header-anchor" href="#处理错误" aria-hidden="true">#</a> 处理错误</h2><h2 id="完整示例" tabindex="-1"><a class="header-anchor" href="#完整示例" aria-hidden="true">#</a> 完整示例</h2><div class="language-typescript line-numbers-mode" data-ext="ts"><pre class="language-typescript"><code><span class="token keyword">import</span> <span class="token punctuation">{</span> Body<span class="token punctuation">,</span> Controller<span class="token punctuation">,</span> Post<span class="token punctuation">,</span> Get<span class="token punctuation">,</span> Delete<span class="token punctuation">,</span> Put<span class="token punctuation">,</span> Param<span class="token punctuation">,</span> Query <span class="token punctuation">}</span> <span class="token keyword">from</span> <span class="token string">&#39;@nestjs/common&#39;</span>

<span class="token decorator"><span class="token at operator">@</span><span class="token function">Controller</span></span><span class="token punctuation">(</span><span class="token string">&#39;user&#39;</span><span class="token punctuation">)</span>
<span class="token keyword">export</span> <span class="token keyword">class</span> <span class="token class-name">UserController</span> <span class="token punctuation">{</span>
  <span class="token decorator"><span class="token at operator">@</span><span class="token function">Post</span></span><span class="token punctuation">(</span><span class="token punctuation">)</span>
  <span class="token function">create</span><span class="token punctuation">(</span><span class="token decorator"><span class="token at operator">@</span><span class="token function">Body</span></span><span class="token punctuation">(</span><span class="token punctuation">)</span> createDto<span class="token operator">:</span> CreateDto<span class="token punctuation">)</span> <span class="token punctuation">{</span>
    <span class="token keyword">return</span> <span class="token string">&#39;&#39;</span>
  <span class="token punctuation">}</span>
  <span class="token decorator"><span class="token at operator">@</span><span class="token function">Get</span></span><span class="token punctuation">(</span><span class="token punctuation">)</span>
  <span class="token function">findAll</span><span class="token punctuation">(</span><span class="token decorator"><span class="token at operator">@</span><span class="token function">Query</span></span><span class="token punctuation">(</span><span class="token punctuation">)</span> query<span class="token operator">:</span> ListAllEntities<span class="token punctuation">)</span> <span class="token punctuation">{</span>
    <span class="token keyword">return</span> <span class="token template-string"><span class="token template-punctuation string">`</span><span class="token string">This action returns all cats (limit: </span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>query<span class="token punctuation">.</span>limit<span class="token interpolation-punctuation punctuation">}</span></span><span class="token string"> items)</span><span class="token template-punctuation string">`</span></span>
  <span class="token punctuation">}</span>

  <span class="token decorator"><span class="token at operator">@</span><span class="token function">Get</span></span><span class="token punctuation">(</span><span class="token string">&#39;:id&#39;</span><span class="token punctuation">)</span>
  <span class="token function">findOne</span><span class="token punctuation">(</span><span class="token decorator"><span class="token at operator">@</span><span class="token function">Param</span></span><span class="token punctuation">(</span><span class="token string">&#39;id&#39;</span><span class="token punctuation">)</span> id<span class="token operator">:</span> <span class="token builtin">string</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
    <span class="token keyword">return</span> <span class="token template-string"><span class="token template-punctuation string">`</span><span class="token string">This action returns a #</span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>id<span class="token interpolation-punctuation punctuation">}</span></span><span class="token string"> cat</span><span class="token template-punctuation string">`</span></span>
  <span class="token punctuation">}</span>

  <span class="token decorator"><span class="token at operator">@</span><span class="token function">Put</span></span><span class="token punctuation">(</span><span class="token string">&#39;:id&#39;</span><span class="token punctuation">)</span>
  <span class="token function">update</span><span class="token punctuation">(</span><span class="token decorator"><span class="token at operator">@</span><span class="token function">Param</span></span><span class="token punctuation">(</span><span class="token string">&#39;id&#39;</span><span class="token punctuation">)</span> id<span class="token operator">:</span> <span class="token builtin">string</span><span class="token punctuation">,</span> <span class="token decorator"><span class="token at operator">@</span><span class="token function">Body</span></span><span class="token punctuation">(</span><span class="token punctuation">)</span> updateCatDto<span class="token operator">:</span> UpdateCatDto<span class="token punctuation">)</span> <span class="token punctuation">{</span>
    <span class="token keyword">return</span> <span class="token template-string"><span class="token template-punctuation string">`</span><span class="token string">This action updates a #</span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>id<span class="token interpolation-punctuation punctuation">}</span></span><span class="token string"> cat</span><span class="token template-punctuation string">`</span></span>
  <span class="token punctuation">}</span>

  <span class="token decorator"><span class="token at operator">@</span><span class="token function">Delete</span></span><span class="token punctuation">(</span><span class="token string">&#39;:id&#39;</span><span class="token punctuation">)</span>
  <span class="token function">remove</span><span class="token punctuation">(</span><span class="token decorator"><span class="token at operator">@</span><span class="token function">Param</span></span><span class="token punctuation">(</span><span class="token string">&#39;id&#39;</span><span class="token punctuation">)</span> id<span class="token operator">:</span> <span class="token builtin">string</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
    <span class="token keyword">return</span> <span class="token template-string"><span class="token template-punctuation string">`</span><span class="token string">This action removes a #</span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>id<span class="token interpolation-punctuation punctuation">}</span></span><span class="token string"> cat</span><span class="token template-punctuation string">`</span></span>
  <span class="token punctuation">}</span>
<span class="token punctuation">}</span>

</code></pre><div class="line-numbers" aria-hidden="true"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><div class="custom-container danger"><p class="custom-container-title">警告</p><p><code>Nest CLI</code> 提供了一个能够自动生成所有这些模板代码的生成器，它帮助我们规避手动建立这些文件，并使开发体验变得更加简单。</p></div><h2 id="最后一步" tabindex="-1"><a class="header-anchor" href="#最后一步" aria-hidden="true">#</a> 最后一步</h2><p>控制器已经准备就绪，可以使用，但是 Nest 依然不知道 <code>Controller</code> 是否存在，所以它不会创建这个类的一个实例。</p><p><strong>控制器总是属于模块</strong>，这就是为什么我们在 @Module() 装饰器中包含 <code>controllers</code> 数组的原因。</p><div class="language-typescript line-numbers-mode" data-ext="ts"><pre class="language-typescript"><code><span class="token doc-comment comment">/**
 * app.modules.ts
 */</span>
<span class="token keyword">import</span> <span class="token punctuation">{</span> Module <span class="token punctuation">}</span> <span class="token keyword">from</span> <span class="token string">&#39;@nestjs/common&#39;</span>
<span class="token keyword">import</span> <span class="token punctuation">{</span> UserController <span class="token punctuation">}</span> <span class="token keyword">from</span> <span class="token string">&#39;./user/user.controller&#39;</span>

<span class="token decorator"><span class="token at operator">@</span><span class="token function">Module</span></span><span class="token punctuation">(</span><span class="token punctuation">{</span>
  controllers<span class="token operator">:</span> <span class="token punctuation">[</span>UserController<span class="token punctuation">]</span><span class="token punctuation">,</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span>
<span class="token keyword">export</span> <span class="token keyword">class</span> <span class="token class-name">AppModule</span> <span class="token punctuation">{</span><span class="token punctuation">}</span>

</code></pre><div class="line-numbers" aria-hidden="true"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>使用 <code>@Module()</code> 装饰器将元数据附加到模块类中，现在，Nest 可以轻松反射（reflect）出哪些控制器（controller）必须被安装。</p><h2 id="类库特有方式" tabindex="-1"><a class="header-anchor" href="#类库特有方式" aria-hidden="true">#</a> 类库特有方式</h2><p>操作响应的第二种方法是使用类库特有的响应对象(Response)。为了注入特定的响应对象，我们需要使用 <code>@Res()</code> 装饰器。 为了对比差异，让我们来重写 Controller：</p><div class="language-typescript line-numbers-mode" data-ext="ts"><pre class="language-typescript"><code><span class="token keyword">import</span> <span class="token punctuation">{</span> Controller<span class="token punctuation">,</span> Get<span class="token punctuation">,</span> Post<span class="token punctuation">,</span> Res<span class="token punctuation">,</span> HttpStatus <span class="token punctuation">}</span> <span class="token keyword">from</span> <span class="token string">&#39;@nestjs/common&#39;</span><span class="token punctuation">;</span>
<span class="token keyword">import</span> <span class="token punctuation">{</span> Response <span class="token punctuation">}</span> <span class="token keyword">from</span> <span class="token string">&#39;express&#39;</span><span class="token punctuation">;</span>

<span class="token decorator"><span class="token at operator">@</span><span class="token function">Controller</span></span><span class="token punctuation">(</span><span class="token string">&#39;user&#39;</span><span class="token punctuation">)</span>
<span class="token keyword">export</span> <span class="token keyword">class</span> <span class="token class-name">UserController</span> <span class="token punctuation">{</span>
  <span class="token decorator"><span class="token at operator">@</span><span class="token function">Post</span></span><span class="token punctuation">(</span><span class="token punctuation">)</span>
  <span class="token function">create</span><span class="token punctuation">(</span><span class="token decorator"><span class="token at operator">@</span><span class="token function">Res</span></span><span class="token punctuation">(</span><span class="token punctuation">)</span> res<span class="token operator">:</span> Response<span class="token punctuation">)</span> <span class="token punctuation">{</span>
    res<span class="token punctuation">.</span><span class="token function">status</span><span class="token punctuation">(</span>HttpStatus<span class="token punctuation">.</span><span class="token constant">CREATED</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">send</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token punctuation">}</span>

  <span class="token decorator"><span class="token at operator">@</span><span class="token function">Get</span></span><span class="token punctuation">(</span><span class="token punctuation">)</span>
  <span class="token function">findAll</span><span class="token punctuation">(</span><span class="token decorator"><span class="token at operator">@</span><span class="token function">Res</span></span><span class="token punctuation">(</span><span class="token punctuation">)</span> res<span class="token operator">:</span> Response<span class="token punctuation">)</span> <span class="token punctuation">{</span>
    res<span class="token punctuation">.</span><span class="token function">status</span><span class="token punctuation">(</span>HttpStatus<span class="token punctuation">.</span><span class="token constant">OK</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">json</span><span class="token punctuation">(</span><span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token punctuation">}</span>
<span class="token punctuation">}</span>

</code></pre><div class="line-numbers" aria-hidden="true"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>尽管此方法有效，并且实际上通过提供对响应对象的完全控制（标头操作，特定于库的功能等）在某些方面提供了更大的灵活性，但应谨慎使用此种方法。通常来说，这种方式非常不清晰，并且有一些缺点。 主要的缺点是代码变得依赖于平台（因为不同的底层库在响应对象（Response）上可能具有不同的 API），并且更加难以测试（必须模拟响应对象等）。</p><p>而且，在上面的示例中，你失去与依赖于 Nest 标准响应处理的 Nest 功能（例如，拦截器（Interceptors） 和 <code>@HttpCode()/@Header()</code> 装饰器）的兼容性。要解决此问题，可以将 passthrough 选项设置为 true，如下所示：</p><div class="language-typescript line-numbers-mode" data-ext="ts"><pre class="language-typescript"><code><span class="token decorator"><span class="token at operator">@</span><span class="token function">Get</span></span><span class="token punctuation">(</span><span class="token punctuation">)</span>
<span class="token function">findAll</span><span class="token punctuation">(</span><span class="token decorator"><span class="token at operator">@</span><span class="token function">Res</span></span><span class="token punctuation">(</span><span class="token punctuation">{</span> passthrough<span class="token operator">:</span> <span class="token boolean">true</span> <span class="token punctuation">}</span><span class="token punctuation">)</span> res<span class="token operator">:</span> Response<span class="token punctuation">)</span> <span class="token punctuation">{</span>
  res<span class="token punctuation">.</span><span class="token function">status</span><span class="token punctuation">(</span>HttpStatus<span class="token punctuation">.</span><span class="token constant">OK</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token keyword">return</span> <span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>

</code></pre><div class="line-numbers" aria-hidden="true"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>现在，就能与底层框架原生的响应对象（Response）进行交互（例如，根据特定条件设置 Cookie 或 HTTP 头），并将剩余的部分留给 Nest 处理。</p></div><!----><footer class="page-meta"><!----><div class="meta-item update-time"><span class="label">上次编辑于: </span><!----></div><!----></footer><!----><!----><!----><!--]--></main><!--]--><!----><!--]--></div><!--]--><!----><!--]--></div>
    <script type="module" src="/doc/assets/app.41440b49.js" defer></script>
  </body>
</html>
